package org.fujene.diskblock.local;

import static org.fujene.diskblock.local.DictionaryDiskBlock.Type.*;

import java.io.File;
import java.io.UnsupportedEncodingException;

import org.fujene.diskblock.DiskBlock;
import org.fujene.memoryblock.MemoryBlock;
import org.fujene.memoryblock.local.LocalDictionaryBlock;
import org.fujene.structure.Constants;
import org.fujene.structure.LookupPointer;
import org.fujene.structure.SearchedTerm;
import org.fujene.toolbox.ByteConverter;

/**
 * DictionaryBlockのサブセットとして機能します。
 */
public class DictionaryDiskBlock extends DiskBlock{

	public DictionaryDiskBlock(File fileDesc) throws Exception{
		super(fileDesc);
	}

	public DictionaryDiskBlock(MemoryBlock memBlock, String dir){
		super(memBlock, dir);
	}

	public enum Type{
		ALL, NEXT, DOCID, INVINDEX, STR,
	}

	// 1単語分の辞書
	private class DictionaryTerm{
		private LookupPointer nextTermPtr;
		private LookupPointer docIDPtr;
		private int strLength;
		private String str;

		/**
		 * 情報読み出し用
		 * 
		 * @throws Exception
		 */
		public DictionaryTerm(int from, Type type) throws Exception{
			if (type == ALL || type == NEXT)
				this.nextTermPtr = ByteConverter.getPtr(getBody(from, PTR), 0);
			else this.nextTermPtr = Constants.EMPTY_PTR;
			from += PTR;
			if (type == ALL || type == DOCID)
				this.docIDPtr = ByteConverter.getPtr(getBody(from, PTR), 0);
			else this.docIDPtr = Constants.EMPTY_PTR;
			if (type == ALL || type == STR){
				from += PTR;
				this.strLength = ByteConverter.byteToInt(getBody(from, STRLEN));
				from += STRLEN;
				try{
					this.str = new String(getBody(from, strLength), "UTF-8");
				}
				catch(UnsupportedEncodingException e){}
			}

		}

		/**
		 * 情報読み出し用
		 * 
		 * @throws Exception
		 */
		public DictionaryTerm(int from) throws Exception{
			this(from, ALL);
		}
	}

	public LookupPointer getNextPointer(int ptr) throws Exception{
		DictionaryTerm ptredDic = new DictionaryTerm(ptr, Type.NEXT);

		if (ptredDic.nextTermPtr.equals(Constants.EMPTY_PTR))
			return null;
		else return ptredDic.nextTermPtr;
	}

	public LookupPointer getDocIDPointer(int ptr) throws Exception{
		DictionaryTerm ptredDic = new DictionaryTerm(ptr, Type.DOCID);

		if (ptredDic.docIDPtr.equals(Constants.EMPTY_PTR))
			return null;
		else return ptredDic.docIDPtr;
	}

	// 情報読み込み
	public SearchedTerm getTerm(int ptr) throws Exception{
		DictionaryTerm ptredDic = new DictionaryTerm(ptr);

		if (ptredDic.nextTermPtr.equals(Constants.EMPTY_PTR)) ptredDic.nextTermPtr = null;
		if (ptredDic.docIDPtr.equals(Constants.EMPTY_PTR)) ptredDic.docIDPtr = null;

		return new SearchedTerm(ptredDic.str, new LookupPointer(this.getID(), ptr), ptredDic.nextTermPtr,
				ptredDic.docIDPtr);
	}

	public int getTermCount() throws Exception{
		return this.getOption(0);
	}

	@Override
	public void readToMemory(MemoryBlock memBlock){
		if (memBlock instanceof LocalDictionaryBlock){
			try{
				memBlock.setOption(0, this.getOption(0));
				memBlock.setOption(1, this.getOption(1));
				memBlock.setBody(this.getBody(0, this.bodySize), 0);
				memBlock.setBodyVacancy(this.bodyVacancy);
			}
			catch(Exception e){}
		}
	}

	@Override
	public byte[] getData(){
		throw new NoSuchMethodError("Unimplemented method");
	}
}
